package cn.huijielong.common.utils;

import cn.huijielong.common.exception.VSException;
import cn.huijielong.common.xss.SQLFilter;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.Assert;

import com.google.gson.Gson;

import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * 查询参数
 *
 * @date 2017-03-14 23:15
 */
public class Query extends LinkedHashMap<String, Object> {
	Logger logger = LoggerFactory.getLogger(Query.class);
	private static final long serialVersionUID = 1L;
	//当前页码
    private int page;
    //每页条数
    private int limit;
    
    public Query() {}
    
    public static Query empty() {
    	return new Query();
    }
    public static Query empty(Map<String, ?> params) {
    	Query q=new Query();
    	if(params!=null)
    		q.putAll(params);
    	return q;
    }

    public Query(Map<String, Object> params){
        this.putAll(params);

        //分页参数
        if(this.containsKey("page"))
        	this.page = this.getInt("page");
       	this.limit =this.getInt("limit");
       	if(this.limit>0)
       		this.put("offset", (page - 1) * limit);
        this.put("page", page);
        this.put("limit", limit);

        //防止SQL注入（因为sidx、order是通过拼接SQL实现排序的，会有SQL注入风险）
        String sidx = (String)params.get("sidx");
        String order = (String)params.get("order");
        if(StringUtils.isNotBlank(sidx)){
            this.put("sidx", SQLFilter.sqlInject(sidx));
        }
        if(StringUtils.isNotBlank(order)){
            this.put("order", SQLFilter.sqlInject(order));
        }

    }

    public int getOffset() {
    	if(this.containsKey("offset"))
    		return this.getInt("offset");
    	else
    		return -1;
    }
    /**
     * 当前页
     * @return
     */
    public int getPage() {
    	if(page==0 && containsKey("page"))
    		return getInt("page");
        return page;
    }
    /**
     * 当前页
     * @param page
     */
    public void setPage(int page) {
        this.page = page;
    }
    /**
     * 每页显示条数
     * @return
     */
    public int getLimit() {
    	if(limit==0 && containsKey("limit"))
    		return getInt("limit");
        return limit;
    }
    /**
     * 每页显示条数
     * @param limit
     */
    public void setLimit(int limit) {
        this.limit = limit;
    }
    public String getString(String key) {
    	Object v=get(key);
    	return v==null?"":v.toString();
    }
    public int getInt(String key) {
    	Object v=get(key);
    	if(v==null)
    		return 0;
    	else if(v instanceof Integer) {
    		return ((Integer)v).intValue();
    	}else {
    		
    		try {
    			return Integer.parseInt(v.toString());
    		}catch(Exception e) {
    			logger.error(key+"对应的值为\""+v+"\"，不能转换成整数，返回0",e);
    			return 0;
    		}
    	}
    }
    public long getLong(String key) {
    	Object v=get(key);
    	if(v==null)
    		return 0L;
    	else if(v instanceof Long) {
    		return ((Long)v).longValue();
    	}else {
    		
    		try {
    			return Long.parseLong(v.toString());
    		}catch(Exception e) {
    			logger.error(key+"对应的值为\""+v+"\"，不能转换成整数，返回0",e);
    			return 0L;
    		}
    	}
    }
    public BigDecimal getDecimal(String key) {
    	Object v=get(key);
    	if(v==null)
    		return BigDecimal.ZERO;
    	else if(v instanceof BigDecimal)
    		return (BigDecimal)v;
    	else {
    		try {
    			return new BigDecimal(v.toString());
    		}catch(Exception e) {
    			logger.error(key+"对应的值为\""+v+"\"，不能转换成数字，返回0",e);
    			return BigDecimal.ZERO;
    		}
    	}
    }
    public Date getDate(String key) {
    	Object v=get(key);
    	if(v==null){
    		return null;
    	}else if(v instanceof Date) {
    		return (Date)v;
    	}else {
    		logger.error(key+"对应的值为\""+v+"\"，不能转换成日期，返回null");
    		return null;
    	}
    }
    public boolean isLimitSql() {
    	return this.page>-1 && this.limit>0;
    }
  
    public Query getQuery(String key) {
    	Object v=this.get(key);
    	if(v==null)
    		return Query.empty();
    	if(v instanceof Map)
    		return Query.empty((Map)v);
    	throw new VSException(v.getClass().getName()+"不能转换为Query");
    }
    public Query addParam(String k,Object v) {
		this.put(k, v);
		return this;
	}
	public Query addParamNotEmpty(String k,Object v) {
		if(v==null || v.toString().isEmpty())
			return this;
		this.put(k, v);
		return this;
	}
	public void isEmpty(String k,String msg) {
		if(!containsKey(k) || get(k)==null) {
			throw new VSException(msg);
		}
	}
	@Override
	public String toString() {
		return new Gson().toJson(this);
	}
	public <T> T toObject(Class<T> c) {
		try {
			Object obj=c.newInstance();
			Field[] fields=c.getDeclaredFields();
			for(Field f:fields) {
				String name=f.getName();
				if(this.containsKey(name)) {
					String typeName=f.getType().getSimpleName();
					Object val=null;
					switch(typeName) {
					case "Integer":
						val=Integer.valueOf(this.getInt(name));
					case "int":
						val=this.getInt(name);
						break;
					case "Long":
						val=Long.valueOf(this.getLong(name));
					case "long":
						val=this.getLong(name);
						break;
					case "BigDecimal":
						val=this.getDecimal(name);
						break;
					case "Date":
						Object v=this.get(name);
						if(v instanceof Date) {
							val=v;
						}else if(v instanceof String) {
							val=DateUtils.parseDate(v.toString());
						}
						break;
					case "String":
						val=this.getString(name);
						break;
					}
					if(val!=null) {
						f.setAccessible(true);
						f.set(obj, val);
					}
				}
			}
			return (T)obj;
		}catch(Exception e) {
			logger.error("Query转对象出错",e);
			return null;
		}
		
	}
	/**
	 * 从request请求获取参数
	 * @param params
	 * @return
	 */
	public static Query createRequest(Map<String, Object> params) {
		Query q = new Query(params);
		Map<String, Object> map=VSUtil.requestToQuery();
		q.putAll(map);
		return q;
	}
	
	/**
	 * 从request请求获取参数
	 * @param params
	 * @return
	 */
	public static Query createRequest() {
		return VSUtil.requestToQuery();
	}
}
